package me.sealer.ssm.controller;

import lombok.extern.slf4j.Slf4j;
import me.sealer.ssm.constant.Dict;
import me.sealer.ssm.constant.ErrorCodeConstant;
import me.sealer.ssm.constant.PermissionConstant;
import me.sealer.ssm.exception.SsmException;
import org.apache.commons.io.FileUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

/**
 * @author sealer
 * @date 2016/09/29
 */
@Slf4j
@Controller
@RequestMapping("/fileOperations")
@RequiresPermissions(value = {PermissionConstant.FILE_MGMT})
public class FileController {
    @Value("${FileUploadPath}")
    private String prefixPath;

    @RequestMapping("/preFileMgmt")
    public String preFileMgmt() {
        return "fileMgmt";
    }

    /**
     * 通过流的方式上传文件
     *
     * @RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
     */
    @RequestMapping(value = "/fileUpload1", method = RequestMethod.POST)
    public String fileUpload(@RequestParam(Dict.FILE) CommonsMultipartFile file, ModelMap modelMap) throws IOException {
        //用来检测程序运行时间
        long startTime = System.currentTimeMillis();
        if (log.isDebugEnabled()) {
            log.debug("fileName：" + file.getOriginalFilename());
        }
        try {
            //获取输出流
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(prefixPath + System.currentTimeMillis() + file.getOriginalFilename()));
            //获取输入流 CommonsMultipartFile 中可以直接得到文件的流
            BufferedInputStream bis = new BufferedInputStream(file.getInputStream());
            int byteRead;
            try {
                while ((byteRead = bis.read()) != -1) {
                    bos.write(byteRead);
                }
            } catch (Exception e) {
                modelMap.put("errorInfo", e.toString());
                return "fileUploadError";
            } finally {
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bos.close();
                }
            }
        } catch (FileNotFoundException e) {
            modelMap.put("errorInfo", e.toString());
            return "fileUploadError";
        }
        long endTime = System.currentTimeMillis();
        if (log.isDebugEnabled()) {
            log.debug("方法一的运行时间：" + String.valueOf(endTime - startTime) + "ms");
        }
        return "fileUploadSuccess";
    }

    /**
     * 采用file.transferTo 来保存上传的文件 多文件上传
     */
    @RequestMapping(value = "/fileUpload2", method = RequestMethod.POST)
    public String fileUpload2(@RequestParam(Dict.FILES) CommonsMultipartFile[] files) throws IOException {
        long startTime = System.currentTimeMillis();

        if (files != null && files.length > 0) {
            //循环获取file数组中得文件
            for (int i = 0; i < files.length; i++) {
                MultipartFile file = files[i];
                //保存文件
                saveFile(file);
            }
        }

        long endTime = System.currentTimeMillis();
        if (log.isDebugEnabled()) {
            log.debug("方法二的运行时间：" + String.valueOf(endTime - startTime) + "ms");
        }
        return "fileUploadSuccess";
    }

    public void saveFile(MultipartFile file) throws IOException {
        log.debug("fileName：" + file.getOriginalFilename());
        String path = prefixPath + System.currentTimeMillis() + file.getOriginalFilename();

        File newFile = new File(path);
        //通过CommonsMultipartFile的方法直接写文件（注意这个时候）
        file.transferTo(newFile);
    }

    /**
     * 采用spring提供的上传文件的方法
     */
    @RequestMapping(value = "/springUpload", method = RequestMethod.POST)
    public String springUpload(HttpServletRequest request) throws IllegalStateException, IOException {
        long startTime = System.currentTimeMillis();
        //将当前上下文初始化给  CommonsMutipartResolver （多部分解析器）
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
                request.getSession().getServletContext());
        //检查form中是否有enctype="multipart/form-data"
        if (multipartResolver.isMultipart(request)) {
            //将request变成多部分request
            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
            //获取multiRequest 中所有的文件名
            Iterator<String> iterator = multiRequest.getFileNames();

            while (iterator.hasNext()) {
                //一次遍历所有文件
                List<MultipartFile> files = multiRequest.getFiles(iterator.next());
                if (files.size() == 0) {
                    return "";
                }
                Iterator<MultipartFile> fileIterator = files.iterator();
                Long currentMillis = System.currentTimeMillis();
                // 遍历多个文件
                while (fileIterator.hasNext()) {
                    MultipartFile file = fileIterator.next();
                    if (file != null) {
                        String path = prefixPath + currentMillis + "-" + file.getOriginalFilename();
                        //上传
                        file.transferTo(new File(path));
                    }
                }
            }
        }
        long endTime = System.currentTimeMillis();
        if (log.isDebugEnabled()) {
            log.debug("方法三的运行时间：" + String.valueOf(endTime - startTime) + "ms");
        }
        return "fileUploadSuccess";
    }

    @RequestMapping("/download")
    public ResponseEntity<byte[]> downloadFile(@RequestParam(value = Dict.FILE_NAME, required = false) String fileName,
                                               @RequestParam(value = Dict.FILE_PATH, required = false) String filePath) throws IOException {
        File file = new File(filePath + fileName);
        if (!file.exists()) {
            throw new SsmException(ErrorCodeConstant.FILE_FILE_NOT_EXISTS, new Object[]{fileName});
        }

        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", fileName);

        ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
        return responseEntity;
    }

}
